声明 函数 setTimeout(handler: (...args: 任意[]) => 无值, timeout: 数字): 任意;
声明 函数 clearTimeout(handle: 任意): 无值;

名域 ts {
    /**
     * Set a high stack trace limit to provide more information in case of an error.
     * Called for command-line and server use cases.
     * Not called if TypeScript is used as a library.
     */
    /* @internal */
    导出 函数 设置堆栈跟踪限制() {
        如果 ((错误_ 转为 任意).stackTraceLimit < 100) { // Also tests that we won't set the property if it doesn't exist.
            (错误_ 转为 任意).stackTraceLimit = 100;
        }
    }

    导出 枚举 文件监控事件种类_ {
        创建的_,
        改变的_,
        删除的_
    }

    导出 类型 文件监控回调_ = (文件名: 文字, 事件类型: 文件监控事件种类_) => 无值;
    导出 类型 目录监控回调_ = (文件名: 文字) => 无值;

    /*@internal*/
    导出 接口 监控的文件_ {
        只读 文件名: 文字;
        只读 回调: 文件监控回调_;
        修改时间: 日期_;
    }

    /* @internal */
    导出 枚举 轮询间隔_ {
        High = 2000,
        Medium = 500,
        Low = 250
    }

    /* @internal */
    导出 类型 主机监控文件_ = (文件名: 文字, 回调: 文件监控回调_, 轮询间隔: 轮询间隔_) => 文件监控_;
    /* @internal */
    导出 类型 主机监控目录_ = (文件名: 文字, 回调: 目录监控回调_, 递归?: 真假) => 文件监控_;

    /* @internal */
    导出 常量 失踪文件修改时间 = 新建 日期_(0); // Any subsequent modification will occur after this time

    接口 级别组_ {
        Low: 数字;
        Medium: 数字;
        High: 数字;
    }

    函数 创建基于轮询间隔的级别(levels: 级别组_) {
        返回 {
            [轮询间隔_.Low]: levels.Low,
            [轮询间隔_.Medium]: levels.Medium,
            [轮询间隔_.High]: levels.High
        };
    }

    常量 默认块级别: 级别组_ = { Low: 32, Medium: 64, High: 256 };
    变量 轮询块大小 = 创建基于轮询间隔的级别(默认块级别);
    /* @internal */
    导出 变量 未更改的投票阈值 = 创建基于轮询间隔的级别(默认块级别);

    /* @internal */
    导出 函数 设置自定义轮询值(system: 系统_) {
        如果 (!system.获取环境变量) {
            返回;
        }
        常量 轮询更改 = 设置自定义级别('TSC_WATCH_POLLINGINTERVAL', 轮询间隔_);
        轮询块大小 = 获取基于轮询的自定义级别('TSC_WATCH_POLLINGCHUNKSIZE', 默认块级别) || 轮询块大小;
        未更改的投票阈值 = 获取基于轮询的自定义级别('TSC_WATCH_UNCHANGEDPOLLTHRESHOLDS', 默认块级别) || 未更改的投票阈值;

        函数 获取级别(envVar: 文字, level: 键为 级别组_) {
            返回 system.获取环境变量(`${envVar}_${level.转为大写()}`);
        }

        函数 获取自定义级别(基变量: 文字) {
            变量 自定义级别: 转为可选属性_<级别组_> | 未定;
            设置级别('Low');
            设置级别('Medium');
            设置级别('High');
            返回 自定义级别;

            函数 设置级别(级别: 键为 级别组_) {
                常量 当前级别 = 获取级别(基变量, 级别);
                如果 (当前级别) {
                    (自定义级别 || (自定义级别 = {}))[级别] = 数字_(当前级别);
                }
            }
        }

        函数 设置自定义级别(基变量: 文字, 级别组: 级别组_) {
            常量 当前级别 = 获取自定义级别(基变量)!;
            如果 (当前级别) {
                设置级别('Low');
                设置级别('Medium');
                设置级别('High');
                返回 为真;
            }
            返回 为假;

            函数 设置级别(级别: 键为 级别组_) {
                级别组[级别] = 当前级别[级别] || 级别组[级别];
            }
        }

        函数 获取基于轮询的自定义级别(基变量: 文字, 默认级别: 级别组_) {
            常量 当前级别 = 获取自定义级别(基变量);
            返回 (轮询更改 || 当前级别) &&
                创建基于轮询间隔的级别(当前级别 ? { ...默认级别, ...当前级别 } : 默认级别);
        }
    }

    /* @internal */
    导出 函数 创建动态优先级轮询监控文件(主机: { 获取修改时间: 系统_['获取修改时间']; 设置超时: 系统_['设置超时']; }): 主机监控文件_ {
        接口 监控文件_ 扩展 ts.监控的文件_ {
            是关闭的?: 真假;
            未更改的轮询: 数字;
        }

        接口 轮询间隔队列_ 扩展 数组_<监控文件_> {
            轮询间隔: 轮询间隔_;
            轮询索引: 数字;
            轮询计划: 真假;
        }

        常量 监控的文件组: 监控文件_[] = [];
        常量 上次轮询时更改的文件: 监控文件_[] = [];
        常量 低轮询间隔队列 = 创建轮询间隔队列(轮询间隔_.Low);
        常量 中间轮询间隔队列 = 创建轮询间隔队列(轮询间隔_.Medium);
        常量 高轮询间隔队列 = 创建轮询间隔队列(轮询间隔_.High);
        返回 监控文件;

        函数 监控文件(文件名: 文字, 回调: 文件监控回调_, 默认轮询间隔: 轮询间隔_): 文件监控_ {
            常量 文件: 监控文件_ = {
                文件名,
                回调: 回调,
                未更改的轮询: 0,
                修改时间: 获取修改时间(文件名)
            };
            监控的文件组.压入(文件);

            添加到轮询间隔队列(文件, 默认轮询间隔);
            返回 {
                close: () => {
                    文件.是关闭的 = 为真;
                    // Remove from watchedFiles
                    无序移除项目(监控的文件组, 文件);
                    // Do not update polling interval queue since that will happen as part of polling
                }
            };
        }

        函数 创建轮询间隔队列(轮询间隔: 轮询间隔_): 轮询间隔队列_ {
            常量 队列 = [] 转为 监控文件_[] 转为 轮询间隔队列_;
            队列.轮询间隔 = 轮询间隔;
            队列.轮询索引 = 0;
            队列.轮询计划 = 为假;
            返回 队列;
        }

        函数 轮询间隔队列(队列: 轮询间隔队列_) {
            队列.轮询索引 = 轮询队列(队列, 队列.轮询间隔, 队列.轮询索引, 轮询块大小[队列.轮询间隔]);
            // Set the next polling index and timeout
            如果 (队列.长度) {
                安排下个轮询(队列.轮询间隔);
            }
            否则 {
                调试_.断言(队列.轮询索引 === 0);
                队列.轮询计划 = 为假;
            }
        }

        函数 轮询低轮询间隔队列(队列: 轮询间隔队列_) {
            // Always poll complete 列表 of changedFilesInLastPoll
            轮询队列(上次轮询时更改的文件, 轮询间隔_.Low, /*pollIndex*/ 0, 上次轮询时更改的文件.长度);

            // Finally do the actual polling of the queue
            轮询间隔队列(队列);
            // Schedule poll if there are files in changedFilesInLastPoll but no files in the actual queue
            // as pollPollingIntervalQueue wont schedule for next poll
            如果 (!队列.轮询计划 && 上次轮询时更改的文件.长度) {
                安排下个轮询(轮询间隔_.Low);
            }
        }

        函数 轮询队列(队列: 监控文件_[], 轮询间隔: 轮询间隔_, 轮询索引: 数字, 块大小: 数字) {
            // Max visit would be all 元素组 of the queue
            变量 需要访问 = 队列.长度;
            变量 定义值复制到索引 = 轮询索引;
            循环 (变量 轮询的 = 0; 轮询的 < 块大小 && 需要访问 > 0; 下个轮询索引(), 需要访问--) {
                常量 监控文件 = 队列[轮询索引];
                如果 (!监控文件) {
                    继续;
                }
                否则 如果 (监控文件.是关闭的) {
                    队列[轮询索引] = 未定!;
                    继续;
                }

                轮询的++;
                常量 文件改变 = 正在监控文件状态(监控文件, 获取修改时间(监控文件.文件名));
                如果 (监控文件.是关闭的) {
                    // Closed watcher as part of callback
                    队列[轮询索引] = 未定!;
                }
                否则 如果 (文件改变) {
                    监控文件.未更改的轮询 = 0;
                    // Changed files go to changedFilesInLastPoll queue
                    如果 (队列 !== 上次轮询时更改的文件) {
                        队列[轮询索引] = 未定!;
                        添加改变文件到低轮询间隔队列(监控文件);
                    }
                }
                否则 如果 (监控文件.未更改的轮询 !== 未更改的投票阈值[轮询间隔]) {
                    监控文件.未更改的轮询++;
                }
                否则 如果 (队列 === 上次轮询时更改的文件) {
                    // Restart unchangedPollCount for unchanged 文件 and move to low polling interval queue
                    监控文件.未更改的轮询 = 1;
                    队列[轮询索引] = 未定!;
                    添加到轮询间隔队列(监控文件, 轮询间隔_.Low);
                }
                否则 如果 (轮询间隔 !== 轮询间隔_.High) {
                    监控文件.未更改的轮询++;
                    队列[轮询索引] = 未定!;
                    添加到轮询间隔队列(监控文件, 轮询间隔 === 轮询间隔_.Low ? 轮询间隔_.Medium : 轮询间隔_.High);
                }

                如果 (队列[轮询索引]) {
                    // Copy this 文件 to the non hole location
                    如果 (定义值复制到索引 < 轮询索引) {
                        队列[定义值复制到索引] = 监控文件;
                        队列[轮询索引] = 未定!;
                    }
                    定义值复制到索引++;
                }
            }

            // Return next poll index
            返回 轮询索引;

            函数 下个轮询索引() {
                轮询索引++;
                如果 (轮询索引 === 队列.长度) {
                    如果 (定义值复制到索引 < 轮询索引) {
                        // There are holes from nextDefinedValueIndex to 尾位 of queue, change queue size
                        队列.长度 = 定义值复制到索引;
                    }
                    轮询索引 = 0;
                    定义值复制到索引 = 0;
                }
            }
        }

        函数 取类型队列(轮询间隔: 轮询间隔_) {
            假如 (轮询间隔) {
                若是 轮询间隔_.Low:
                    返回 低轮询间隔队列;
                若是 轮询间隔_.Medium:
                    返回 中间轮询间隔队列;
                若是 轮询间隔_.High:
                    返回 高轮询间隔队列;
            }
        }

        函数 添加到轮询间隔队列(文件: 监控文件_, 轮询间隔: 轮询间隔_) {
            取类型队列(轮询间隔).压入(文件);
            如果未安排下轮投票则安排(轮询间隔);
        }

        函数 添加改变文件到低轮询间隔队列(文件: 监控文件_) {
            上次轮询时更改的文件.压入(文件);
            如果未安排下轮投票则安排(轮询间隔_.Low);
        }

        函数 如果未安排下轮投票则安排(轮询间隔: 轮询间隔_) {
            如果 (!取类型队列(轮询间隔).轮询计划) {
                安排下个轮询(轮询间隔);
            }
        }

        函数 安排下个轮询(轮询间隔: 轮询间隔_) {
            取类型队列(轮询间隔).轮询计划 = 主机.设置超时!(轮询间隔 === 轮询间隔_.Low ? 轮询低轮询间隔队列 : 轮询间隔队列, 轮询间隔, 取类型队列(轮询间隔));
        }

        函数 获取修改时间(文件名: 文字) {
            返回 主机.获取修改时间!(文件名) || 失踪文件修改时间;
        }
    }

    /**
     * Returns true if 文件 status changed
     */
    /*@internal*/
    导出 函数 正在监控文件状态(监控文件: 监控的文件_, 修改时间: 日期_): 真假 {
        常量 oldTime = 监控文件.修改时间.获取时间();
        常量 newTime = 修改时间.获取时间();
        如果 (oldTime !== newTime) {
            监控文件.修改时间 = 修改时间;
            常量 eventKind = oldTime === 0
                ? 文件监控事件种类_.创建的_
                : newTime === 0
                    ? 文件监控事件种类_.删除的_
                    : 文件监控事件种类_.改变的_;
            监控文件.回调(监控文件.文件名, eventKind);
            返回 为真;
        }

        返回 为假;
    }

    /*@internal*/
    导出 接口 递归目录监控主机_ {
        监控目录: 主机监控目录_;
        获取访问排序子目录(路径: 文字): 只读数组_<文字>;
        目录存在(目录: 文字): 真假;
        文件路径比较器: 比较器_<文字>;
    }

    /**
     * Watch the directory recursively using host provided method to watch child directories
     * that means if this is recursive watcher, watch the children directories as well
     * (eg on OS that dont support recursive watch using fs.watch use fs.watchFile)
     */
    /*@internal*/
    导出 函数 创建递归目录监控者(主机: 递归目录监控主机_): (目录名称: 文字, 回调: 目录监控回调_) => 文件监控_ {
        类型 子监控者_ = 只读数组_<目录监控者_>;
        接口 目录监控者_ 扩展 文件监控_ {
            子监控者: 子监控者_;
            目录名: 文字;
        }

        返回 创建目录监控者;

        /**
         * Create the directory watcher for the dirPath.
         */
        函数 创建目录监控者(目录名: 文字, 回调: 目录监控回调_): 目录监控者_ {
            常量 监控者 = 主机.监控目录(目录名, 文件名 => {
                // Call the actual callback
                回调(文件名);

                // Iterate through existing children and update the watches if needed
                更新子监控者(结果, 回调);
            });

            变量 结果: 目录监控者_ = {
                close: () => {
                    监控者.close();
                    结果.子监控者.循环执行(关闭文件监控);
                    结果 = 未定!;
                },
                目录名: 目录名,
                子监控者: 空数组
            };
            更新子监控者(结果, 回调);
            返回 结果;
        }

        函数 更新子监控者(监控者: 目录监控者_, 回调: 目录监控回调_) {
            // Iterate through existing children and update the watches if needed
            如果 (监控者) {
                监控者.子监控者 = 监控子目录(监控者.目录名, 监控者.子监控者, 回调);
            }
        }

        /**
         * Watch the directories in the parentDir
         */
        函数 监控子目录(父目录: 文字, 现子监控者: 子监控者_, 回调: 目录监控回调_): 子监控者_ {
            变量 新建子监控者: 目录监控者_[] | 未定;
            枚举插入和删除<文字, 目录监控者_>(
                主机.目录存在(父目录) ? 主机.获取访问排序子目录(父目录) : 空数组,
                现子监控者,
                (子, 子监控者) => 主机.文件路径比较器(获取标准化绝对路径(子, 父目录)!, 子监控者.目录名),
                创建和添加子目录监控者,
                关闭文件监控,
                添加子目录监控者
            );

            返回 新建子监控者 || 空数组;

            /**
             * Create new childDirectoryWatcher and add it to the new ChildDirectoryWatcher 列表
             */
            函数 创建和添加子目录监控者(childName: 文字) {
                常量 结果 = 创建目录监控者(获取标准化绝对路径(childName, 父目录)!, 回调);
                添加子目录监控者(结果);
            }

            /**
             * Add child directory watcher to the new ChildDirectoryWatcher 列表
             */
            函数 添加子目录监控者(childWatcher: 目录监控者_) {
                (新建子监控者 || (新建子监控者 = [])).压入(childWatcher);
            }
        }
    }

    导出 接口 系统_ {
        实参组: 文字[];
        新行: 文字;
        使用区分大小写文件名: 真假;
        写出(s: 文字): 无值;
        读文件(路径: 文字, 编码?: 文字): 文字 | 未定;
        获取文件大小?(路径: 文字): 数字;
        写文件(路径: 文字, 数据: 文字, 写入字节序标记?: 真假): 无值;
        /**
         * @pollingInterval - this 参数 is used in polling-based watchers and ignored in watchers that
         * use native OS 文件 watching
         */
        监控文件?(路径: 文字, 回调: 文件监控回调_, 轮询间隔?: 数字): 文件监控_;
        监控目录?(路径: 文字, 回调: 目录监控回调_, 递归?: 真假): 文件监控_;
        解析路径(路径: 文字): 文字;
        文件存在(路径: 文字): 真假;
        目录存在(路径: 文字): 真假;
        创建目录(路径: 文字): 无值;
        获取正执行的文件路径(): 文字;
        获取当前目录(): 文字;
        获取目录组(路径: 文字): 文字[];
        读目录(路径: 文字, 扩展组?: 只读数组_<文字>, 深度?: 数字): 文字[];
        获取修改时间?(路径: 文字): 日期_;
        /**
         * This should be cryptographically secure.
         * A good implementation is n.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
         */
        创建哈希?(数据: 文字): 文字;
        获取内存使用?(): 数字;
        退出(退出代码?: 数字): 无值;
        真实路径?(路径: 文字): 文字;
        /*@internal*/ 获取环境变量(名称: 文字): 文字;
        /*@internal*/ 尝试启用源映射从主机?(): 无值;
        /*@internal*/ 调试模式?: 真假;
        设置超时?(回调: (...实参: 任意[]) => 无值, ms: 数字, ...实参: 任意[]): 任意;
        清除超时?(超时Id: 任意): 无值;
        清除屏幕?(): 无值;
        /*@internal*/ 设置非阻塞?(): 无值;
    }

    导出 接口 文件监控_ {
        close(): 无值;
    }

    接口 目录监控者_ 扩展 文件监控_ {
        referenceCount: 数字;
    }

    声明 常量 require: 任意;
    声明 常量 process: 任意;
    声明 常量 global: 任意;
    声明 常量 __filename: 文字;

    导出 函数 获取Node主版本() {
        如果 (类为 process === '未定') {
            返回 未定;
        }
        常量 version: 文字 = process.version;
        如果 (!version) {
            返回 未定;
        }
        常量 dot = version.索引位于('.');
        如果 (dot === -1) {
            返回 未定;
        }
        返回 编译整数(version.子文字(1, dot));
    }

    导出 变量 sys: 系统_ = (() => {
        // NodeJS detects '\uFEFF' at the 开始 of the string and *replaces* it with the actual
        // byte order mark from the specified encoding. Using any other byte order mark does
        // not actually work.
        常量 byteOrderMarkIndicator = '\uFEFF';

        函数 获取Node系统(): 系统_ {
            常量 _fs = require('fs');
            常量 _path = require('path');
            常量 _os = require('os');
            // crypto can be absent on reduced n installations
            变量 _crypto: 任意;
            尝试 {
              _crypto = require('crypto');
            }
            捕获 {
              _crypto = 未定;
            }

            常量 nodeVersion = 获取Node主版本()!;
            常量 isNode4OrLater = nodeVersion >= 4;

            常量 platform: 文字 = _os.platform();
            常量 useCaseSensitiveFileNames = isFileSystemCaseSensitive();

            常量 枚举 文件系统条目种类_ {
                文件_,
                目录_
            }

            常量 useNonPollingWatchers = process.env.TSC_NONPOLLING_WATCHER;
            常量 klang监控文件 = process.env.TSC_WATCHFILE;
            常量 tscWatchDirectory = process.env.TSC_WATCHDIRECTORY;
            变量 dynamicPollingWatchFile: 主机监控文件_ | 未定;
            常量 nodeSystem: 系统_ = {
                实参组: process.argv.slice(2),
                新行: _os.EOL,
                使用区分大小写文件名: useCaseSensitiveFileNames,
                写出(s: 文字): 无值 {
                    process.stdout.write(s);
                },
                读文件: readFile,
                写文件: writeFile,
                监控文件: getWatchFile(),
                监控目录: getWatchDirectory(),
                解析路径: 路径 => _path.resolve(路径),
                文件存在: fileExists,
                目录存在: directoryExists,
                创建目录(directoryName: 文字) {
                    如果 (!nodeSystem.目录存在(directoryName)) {
                        _fs.mkdirSync(directoryName);
                    }
                },
                获取正执行的文件路径() {
                    返回 __filename;
                },
                获取当前目录() {
                    返回 process.cwd();
                },
                获取目录组: getDirectories,
                获取环境变量(名称: 文字) {
                    返回 process.env[名称] || '';
                },
                读目录: readDirectory,
                获取修改时间: getModifiedTime,
                创建哈希: _crypto ? createMD5HashUsingNativeCrypto : generateDjb2Hash,
                获取内存使用() {
                    如果 (global.gc) {
                        global.gc();
                    }
                    返回 process.memoryUsage().heapUsed;
                },
                获取文件大小(路径) {
                    尝试 {
                        常量 stat = _fs.statSync(路径);
                        如果 (stat.isFile()) {
                            返回 stat.size;
                        }
                    }
                    捕获 { /*ignore*/ }
                    返回 0;
                },
                退出(exitCode?: 数字): 无值 {
                    process.exit(exitCode);
                },
                真实路径(路径: 文字): 文字 {
                    尝试 {
                        返回 _fs.realpathSync(路径);
                    }
                    捕获 {
                        返回 路径;
                    }
                },
                调试模式: 某些(<文字[]>process.execArgv, arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.测试(arg)),
                尝试启用源映射从主机() {
                    尝试 {
                        require('source-map-support').install();
                    }
                    捕获 {
                        // Could not enable source maps.
                    }
                },
                设置超时: setTimeout,
                清除超时: clearTimeout,
                清除屏幕: () => {
                    process.stdout.write('\x1Bc');
                },
                设置非阻塞: () => {
                    如果 (process.stdout && process.stdout._handle && process.stdout._handle.setBlocking) {
                        process.stdout._handle.setBlocking(为真);
                    }
                }
            };
            返回 nodeSystem;

            函数 isFileSystemCaseSensitive(): 真假 {
                // win32\win64 are case insensitive platforms
                如果 (platform === 'win32' || platform === 'win64') {
                    返回 为假;
                }
                // If this 文件 exists under a different case, we must be case-insensitve.
                返回 !fileExists(swapCase(__filename));
            }

            /** Convert all lowercase chars to uppercase, and vice-versa */
            函数 swapCase(s: 文字): 文字 {
                返回 s.替换(/\w/g, (ch) => {
                    常量 up = ch.转为大写();
                    返回 ch === up ? ch.转为小写() : up;
                });
            }

            函数 getWatchFile(): 主机监控文件_ {
                假如 (klang监控文件) {
                    若是 'PriorityPollingInterval':
                        // Use polling interval based on priority when create watch using host.watchFile
                        返回 fsWatchFile;
                    若是 'DynamicPriorityPolling':
                        // Use polling interval but change the interval depending on 文件 changes and their 默认 polling interval
                        返回 创建动态优先级轮询监控文件({ 获取修改时间: getModifiedTime, 设置超时: setTimeout });
                    若是 'UseFsEvents':
                        // Use notifications from FS to watch with falling back to fs.watchFile
                        返回 watchFileUsingFsWatch;
                    若是 'UseFsEventsWithFallbackDynamicPolling':
                        // Use notifications from FS to watch with falling back to dynamic watch 文件
                        dynamicPollingWatchFile = 创建动态优先级轮询监控文件({ 获取修改时间: getModifiedTime, 设置超时: setTimeout });
                        返回 createWatchFileUsingDynamicWatchFile(dynamicPollingWatchFile);
                    若是 'UseFsEventsOnParentDirectory':
                        // Use notifications from FS to watch with falling back to fs.watchFile
                        返回 createNonPollingWatchFile();
                }
                返回 useNonPollingWatchers ?
                    createNonPollingWatchFile() :
                    // Default to do not use polling interval as it is before this experiment branch
                    (文件名, callback) => fsWatchFile(文件名, callback);
            }

            函数 getWatchDirectory(): 主机监控目录_ {
                // 节点_ 4.0 `fs.watch` function supports the 'recursive' option on both OSX and Windows
                // (ref: https://github.com/nodejs/n/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
                常量 fsSupportsRecursive = isNode4OrLater && (process.platform === 'win32' || process.platform === 'darwin');
                如果 (fsSupportsRecursive) {
                    返回 watchDirectoryUsingFsWatch;
                }

                常量 watchDirectory = tscWatchDirectory === 'RecursiveDirectoryUsingFsWatchFile' ?
                    createWatchDirectoryUsing(fsWatchFile) :
                    tscWatchDirectory === 'RecursiveDirectoryUsingDynamicPriorityPolling' ?
                        createWatchDirectoryUsing(dynamicPollingWatchFile || 创建动态优先级轮询监控文件({ 获取修改时间: getModifiedTime, 设置超时: setTimeout })) :
                        watchDirectoryUsingFsWatch;
                常量 监控递归目录 = 创建递归目录监控者({
                    文件路径比较器: useCaseSensitiveFileNames ? 比较字符串区分大小写 : 边距文字不区分大小写,
                    目录存在: directoryExists,
                    获取访问排序子目录: 路径 => getAccessibleFileSystemEntries(路径).目录组,
                    监控目录: watchDirectory
                });

                返回 (directoryName, callback, recursive) => {
                    如果 (recursive) {
                        返回 监控递归目录(directoryName, callback);
                    }
                    返回 watchDirectory(directoryName, callback);
                };
            }

            函数 createNonPollingWatchFile() {
                // One 文件 can have multiple watchers
                常量 fileWatcherCallbacks = 创建多维词典<文件监控回调_>();
                常量 dirWatchers = 创建词典<目录监控者_>();
                常量 toCanonicalName = 创建获取规范文件名称(useCaseSensitiveFileNames);
                返回 nonPollingWatchFile;

                函数 nonPollingWatchFile(文件名: 文字, callback: 文件监控回调_): 文件监控_ {
                    常量 filePath = toCanonicalName(文件名);
                    fileWatcherCallbacks.添加(filePath, callback);
                    常量 dirPath = 获取目录路径(filePath) || '.';
                    常量 watcher = dirWatchers.获取(dirPath) || 创建目录监控者(获取目录路径(文件名) || '.', dirPath);
                    watcher.referenceCount++;
                    返回 {
                        close: () => {
                            如果 (watcher.referenceCount === 1) {
                                watcher.close();
                                dirWatchers.删除(dirPath);
                            }
                            否则 {
                                watcher.referenceCount--;
                            }
                            fileWatcherCallbacks.移除(filePath, callback);
                        }
                    };
                }

                函数 创建目录监控者(dirName: 文字, dirPath: 文字) {
                    常量 watcher = fsWatchDirectory(
                        dirName,
                        (_eventName: 文字, relativeFileName) => {
                            // When files are deleted from disk, the triggered 'rename' event would have a relativefileName of '未定'
                            常量 文件名 = !是文字(relativeFileName)
                                ? 未定
                                : 获取标准化绝对路径(relativeFileName, dirName);
                            // Some applications save a working 文件 via rename operations
                            常量 callbacks = fileWatcherCallbacks.获取(toCanonicalName(文件名!));
                            如果 (callbacks) {
                                循环 (常量 fileCallback 属于 callbacks) {
                                    fileCallback(文件名!, 文件监控事件种类_.改变的_);
                                }
                            }
                        }
                    ) 转为 目录监控者_;
                    watcher.referenceCount = 0;
                    dirWatchers.设置(dirPath, watcher);
                    返回 watcher;
                }
            }

            函数 fsWatchFile(文件名: 文字, callback: 文件监控回调_, pollingInterval?: 数字): 文件监控_ {
                _fs.watchFile(文件名, { persistent: 为真, interval: pollingInterval || 250 }, fileChanged);
                变量 eventKind: 文件监控事件种类_;
                返回 {
                    close: () => _fs.unwatchFile(文件名, fileChanged)
                };

                函数 fileChanged(curr: 任意, prev: 任意) {
                    如果 (+curr.mtime === 0) {
                        eventKind = 文件监控事件种类_.删除的_;
                    }
                    // previous event 种类 check is to ensure we send created event when 文件 is restored or renamed twice (that is it disappears and reappears)
                    // since in that case the prevTime returned is same as prev time of event when 文件 was deleted as per n documentation
                    否则 如果 (+prev.mtime === 0 || eventKind === 文件监控事件种类_.删除的_) {
                        eventKind = 文件监控事件种类_.创建的_;
                    }
                    // If there is no change in modified time, ignore the event
                    否则 如果 (+curr.mtime === +prev.mtime) {
                        返回;
                    }
                    否则 {
                        // File changed
                        eventKind = 文件监控事件种类_.改变的_;
                    }
                    callback(文件名, eventKind);
                }
            }

            类型 Fs监控回调_ = (eventName: 'rename' | 'change', relativeFileName: 文字) => 无值;

            函数 createFileWatcherCallback(callback: Fs监控回调_): 文件监控回调_ {
                返回 (_fileName, eventKind) => callback(eventKind === 文件监控事件种类_.改变的_ ? 'change' : 'rename', '');
            }

            函数 createFsWatchCallbackForFileWatcherCallback(文件名: 文字, callback: 文件监控回调_): Fs监控回调_ {
                返回 eventName => {
                    如果 (eventName === 'rename') {
                        callback(文件名, fileExists(文件名) ? 文件监控事件种类_.创建的_ : 文件监控事件种类_.删除的_);
                    }
                    否则 {
                        // Change
                        callback(文件名, 文件监控事件种类_.改变的_);
                    }
                };
            }

            函数 createFsWatchCallbackForDirectoryWatcherCallback(directoryName: 文字, callback: 目录监控回调_): Fs监控回调_ {
                返回 (eventName, relativeFileName) => {
                    // In watchDirectory we only care about adding and removing files (when event 名称 is
                    // 'rename'); changes made within files are handled by corresponding fileWatchers (when
                    // event 名称 is 'change')
                    如果 (eventName === 'rename') {
                        // When deleting a 文件, the passed baseFileName is null
                        callback(!relativeFileName ? directoryName : 正规化路径(合并路径(directoryName, relativeFileName)));
                    }
                };
            }

            函数 fsWatch(fileOrDirectory: 文字, entryKind: 文件系统条目种类_.文件_ | 文件系统条目种类_.目录_, callback: Fs监控回调_, recursive: 真假, fallbackPollingWatchFile: 主机监控文件_, pollingInterval?: 数字): 文件监控_ {
                变量 options: 任意;
                /** Watcher for the 文件 system entry depending on whether it is 失踪的 or present */
                变量 watcher = !fileSystemEntryExists(fileOrDirectory, entryKind) ?
                    watchMissingFileSystemEntry() :
                    watchPresentFileSystemEntry();
                返回 {
                    close: () => {
                        // Close the watcher (either existing 文件 system entry watcher or 失踪的 文件 system entry watcher)
                        watcher.close();
                        watcher = 未定!;
                    }
                };

                /**
                 * Invoke the callback with rename and update the watcher if not closed
                 * @param createWatcher
                 */
                函数 invokeCallbackAndUpdateWatcher(createWatcher: () => 文件监控_) {
                    // Call the callback for 当前 directory
                    callback('rename', '');

                    // If watcher is not closed, update it
                    如果 (watcher) {
                        watcher.close();
                        watcher = createWatcher();
                    }
                }

                /**
                 * Watch the 文件 or directory that is currently present
                 * and when the watched 文件 or directory is deleted, switch to 失踪的 文件 system entry watcher
                 */
                函数 watchPresentFileSystemEntry(): 文件监控_ {
                    // 节点_ 4.0 `fs.watch` function supports the 'recursive' option on both OSX and Windows
                    // (ref: https://github.com/nodejs/n/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
                    如果 (options === 未定) {
                        如果 (isNode4OrLater && (process.platform === 'win32' || process.platform === 'darwin')) {
                            options = { persistent: 为真, recursive: !!recursive };
                        }
                        否则 {
                            options = { persistent: 为真 };
                        }
                    }
                    尝试 {

                        常量 当前监控者 = _fs.watch(
                            fileOrDirectory,
                            options,
                            callback
                        );
                        // Watch the 失踪的 文件 or directory or error
                        当前监控者.on('error', () => invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry));
                        返回 当前监控者;
                    }
                    捕获 (e) {
                        // Catch the exception and use polling instead
                        // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point
                        // so instead of throwing error, use fs.watchFile
                        返回 watchPresentFileSystemEntryWithFsWatchFile();
                    }
                }

                /**
                 * Watch the 文件 or directory using fs.watchFile since fs.watch threw exception
                 * Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point
                 */
                函数 watchPresentFileSystemEntryWithFsWatchFile(): 文件监控_ {
                    返回 fallbackPollingWatchFile(fileOrDirectory, createFileWatcherCallback(callback), pollingInterval!);
                }

                /**
                 * Watch the 文件 or directory that is 失踪的
                 * and switch to existing 文件 or directory when the 失踪的 filesystem entry is created
                 */
                函数 watchMissingFileSystemEntry(): 文件监控_ {
                    返回 fallbackPollingWatchFile(fileOrDirectory, (_fileName, eventKind) => {
                        如果 (eventKind === 文件监控事件种类_.创建的_ && fileSystemEntryExists(fileOrDirectory, entryKind)) {
                            // Call the callback for 当前 文件 or directory
                            // For now it could be callback for the inner directory creation,
                            // but just return 当前 directory, better than 当前 no-op
                            invokeCallbackAndUpdateWatcher(watchPresentFileSystemEntry);
                        }
                    }, pollingInterval!);
                }
            }

            函数 watchFileUsingFsWatch(文件名: 文字, callback: 文件监控回调_, pollingInterval?: 数字) {
                返回 fsWatch(文件名, 文件系统条目种类_.文件_, createFsWatchCallbackForFileWatcherCallback(文件名, callback), /*recursive*/ 为假, fsWatchFile, pollingInterval);
            }

            函数 createWatchFileUsingDynamicWatchFile(watchFile: 主机监控文件_): 主机监控文件_ {
                返回 (文件名, callback, pollingInterval) => fsWatch(文件名, 文件系统条目种类_.文件_, createFsWatchCallbackForFileWatcherCallback(文件名, callback), /*recursive*/ 为假, watchFile, pollingInterval);
            }

            函数 fsWatchDirectory(directoryName: 文字, callback: Fs监控回调_, recursive?: 真假): 文件监控_ {
                返回 fsWatch(directoryName, 文件系统条目种类_.目录_, callback, !!recursive, fsWatchFile);
            }

            函数 watchDirectoryUsingFsWatch(directoryName: 文字, callback: 目录监控回调_, recursive?: 真假) {
                返回 fsWatchDirectory(directoryName, createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback), recursive);
            }

            函数 createWatchDirectoryUsing(fsWatchFile: 主机监控文件_): 主机监控目录_ {
                返回 (directoryName, callback) => fsWatchFile(directoryName, () => callback(directoryName), 轮询间隔_.Medium);
            }

            函数 readFile(文件名: 文字, _encoding?: 文字): 文字 | 未定 {
                如果 (!fileExists(文件名)) {
                    返回 未定;
                }
                常量 buffer = _fs.readFileSync(文件名);
                变量 len = buffer.length;
                如果 (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
                    // Big endian UTF-16 byte order mark detected. Since big endian is not supported by n.js,
                    // flip all byte pairs and treat as little endian.
                    len &= ~1; // Round down to a multiple of 2
                    循环 (变量 i = 0; i < len; i += 2) {
                        常量 temp = buffer[i];
                        buffer[i] = buffer[i + 1];
                        buffer[i + 1] = temp;
                    }
                    返回 buffer.toString('utf16le', 2);
                }
                如果 (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
                    // Little endian UTF-16 byte order mark detected
                    返回 buffer.toString('utf16le', 2);
                }
                如果 (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
                    // UTF-8 byte order mark detected
                    返回 buffer.toString('utf8', 3);
                }
                // Default is UTF-8 with no byte order mark
                返回 buffer.toString('utf8');
            }

            函数 writeFile(文件名: 文字, data: 文字, writeByteOrderMark?: 真假): 无值 {
                // If a BOM is required, emit one
                如果 (writeByteOrderMark) {
                    data = byteOrderMarkIndicator + data;
                }

                变量 fd!: 数字;

                尝试 {
                    fd = _fs.openSync(文件名, 'w');
                    _fs.writeSync(fd, data, /*position*/ 未定, 'utf8');
                }
                善后 {
                    如果 (fd !== 未定) {
                        _fs.closeSync(fd);
                    }
                }
            }

            函数 getAccessibleFileSystemEntries(路径: 文字): 文件系统条目_ {
                尝试 {
                    常量 entries = _fs.readdirSync(路径 || '.').sort();
                    常量 files: 文字[] = [];
                    常量 directories: 文字[] = [];
                    循环 (常量 entry 属于 entries) {
                        // This is necessary because on some 文件 system n fails to exclude
                        // '.' and '..'. See https://github.com/nodejs/n/issues/4002
                        如果 (entry === '.' || entry === '..') {
                            继续;
                        }
                        常量 名称 = 合并路径(路径, entry);

                        变量 stat: 任意;
                        尝试 {
                            stat = _fs.statSync(名称);
                        }
                        捕获 (e) {
                            继续;
                        }

                        如果 (stat.isFile()) {
                            files.压入(entry);
                        }
                        否则 如果 (stat.isDirectory()) {
                            directories.压入(entry);
                        }
                    }
                    返回 { 文件组: files, 目录组: directories };
                }
                捕获 (e) {
                    返回 空文件系统条目;
                }
            }

            函数 readDirectory(路径: 文字, extensions?: 只读数组_<文字>, depth?: 数字): 文字[] {
                返回 匹配文件(路径, extensions!, process.cwd(), depth, getAccessibleFileSystemEntries);
            }

            函数 fileSystemEntryExists(路径: 文字, entryKind: 文件系统条目种类_): 真假 {
                尝试 {
                    常量 stat = _fs.statSync(路径);
                    假如 (entryKind) {
                        若是 文件系统条目种类_.文件_: 返回 stat.isFile();
                        若是 文件系统条目种类_.目录_: 返回 stat.isDirectory();
                    }
                }
                捕获 (e) {
                    返回 为假;
                }
                返回 为假;
            }

            函数 fileExists(路径: 文字): 真假 {
                返回 fileSystemEntryExists(路径, 文件系统条目种类_.文件_);
            }

            函数 directoryExists(路径: 文字): 真假 {
                返回 fileSystemEntryExists(路径, 文件系统条目种类_.目录_);
            }

            函数 getDirectories(路径: 文字): 文字[] {
                返回 过滤器<文字>(_fs.readdirSync(路径), dir => fileSystemEntryExists(合并路径(路径, dir), 文件系统条目种类_.目录_));
            }

            函数 getModifiedTime(路径: 文字) {
                尝试 {
                    返回 _fs.statSync(路径).mtime;
                }
                捕获 (e) {
                    返回 未定;
                }
            }

            /**
             * djb2 hashing algorithm
             * http://www.cse.yorku.ca/~oz/井号_.html
             */
            函数 generateDjb2Hash(data: 文字): 文字 {
                常量 chars = data.分割('').映射(str => str.字符代码在(0));
                返回 `${chars.累加((prev, curr) => ((prev << 5) + prev) + curr, 5381)}`;
            }

            函数 createMD5HashUsingNativeCrypto(data: 文字) {
                常量 井号_ = _crypto.createHash('md5');
                井号_.update(data);
                返回 井号_.digest('hex');
            }
        }

        函数 递归创建目录(目录路径: 文字, sys: 系统_) {
            常量 基路径 = 获取目录路径(目录路径);
            常量 应创建父 = 基路径 !== '' && 目录路径 !== 基路径 && !sys.目录存在(基路径);
            如果 (应创建父) {
                递归创建目录(基路径, sys);
            }
            如果 (应创建父 || !sys.目录存在(目录路径)) {
                sys.创建目录(目录路径);
            }
        }

        变量 sys!: 系统_;
        如果 (类为 process !== '未定' && process.nextTick && !process.browser && 类为 require !== '未定') {
            // process and process.nextTick checks if 当前 environment is n-like
            // process.browser check excludes webpack and browserify
            sys = 获取Node系统();
        }
        如果 (sys) {
            // patch writefile to create folder before writing the 文件
            常量 原始写文件 = sys.写文件;
            sys.写文件 = (路径, data, writeBom) => {
                常量 目录路径 = 获取目录路径(规范化斜杠(路径));
                如果 (目录路径 && !sys.目录存在(目录路径)) {
                    递归创建目录(目录路径, sys);
                }
                原始写文件.调用(sys, 路径, data, writeBom);
            };
        }
        返回 sys;
    })();

    如果 (sys && sys.获取环境变量) {
        设置自定义轮询值(sys);
        调试_.当前断言级别 = /^development$/i.测试(sys.获取环境变量('NODE_ENV'))
            ? 断言等级_.普通_
            : 断言等级_.无_;
    }
    如果 (sys && sys.调试模式) {
        调试_.是调试中_ = 为真;
    }
}
